/*
 * Niiuzu
 * Copyright (C) 2011  Thierry Nowak
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.niiuzu.server.rpc.impl;

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.niiuzu.server.dao.DaoFactory;
import com.niiuzu.server.dao.FeedChannelDao;
import com.niiuzu.server.dao.FeedEntryDao;
import com.niiuzu.shared.exception.ServiceRpcException;
import com.niiuzu.shared.model.FeedChannel;
import com.niiuzu.shared.model.FeedChannelGroup;
import com.niiuzu.shared.model.FeedEntry;
import com.niiuzu.shared.model.FeedStyle;
import com.niiuzu.shared.rpc.FeedService;

/**
 * Implémentation du service dédié aux flux.
 */
public class FeedServiceImpl extends RemoteServiceServlet implements
		FeedService {

	private static final long serialVersionUID = -8128897257688261021L;

	private static final Logger LOGGER = Logger.getLogger(FeedServiceImpl.class
			.getName());

	@Override
	public FeedEntry[] recoverFeedEntries(FeedChannel[] channels)
			throws ServiceRpcException {

		LOGGER.info("Lancement de l'interrogation d'une liste de flux");

		FeedEntry[] entries = null;

		try {

			FeedEntryDao feedEntryDao = getFeedEntryDao();

			List<FeedEntry> entryList = feedEntryDao
					.getEntriesFromChannels(channels);
			entries = entryList.toArray(new FeedEntry[entryList.size()]);

		} catch (Throwable e) {
			LOGGER.log(Level.SEVERE,
					"Erreur lors de la récupération de données", e);
			throw new ServiceRpcException(e);
		} finally {
			LOGGER.info("Fin de l'interrogation de la liste de flux");
		}

		return entries;
	}

	@Override
	public FeedChannel createChannel(String link, String name,
			FeedChannelGroup channelGroup) throws ServiceRpcException {

		LOGGER.info("Création d'une nouvelle instance de flux");

		FeedChannel channel = null;

		try {

			FeedEntryDao feedEntryDao = getFeedEntryDao();

			channel = feedEntryDao.createChannelFromLink(link);
			channel.setName(name);
			channel.setChannelGroupUid(channelGroup.getUid());

			FeedChannelDao feedChannelDao = getFeedChannelDao();
			feedChannelDao.createOrUpdateFeedChannel(channel);

		} catch (Throwable e) {
			LOGGER.log(Level.SEVERE,
					"Erreur lors de création d'une nouvelle instance de flux",
					e);
			throw new ServiceRpcException(e);
		} finally {
			LOGGER.info("Fin de la création d'un nouvelle instance de flux");
		}

		return channel;
	}

	@Override
	public FeedChannelGroup createChannelGroup(String name, FeedStyle style)
			throws ServiceRpcException {

		LOGGER.info("Création d'un nouvelle instance de thème");

		FeedChannelGroup channelGroup = null;

		try {
			channelGroup = new FeedChannelGroup();
			channelGroup.setName(name);
			channelGroup.setStyle(style);

			FeedChannelDao feedChannelDao = getFeedChannelDao();
			feedChannelDao.createOrUpdateFeedChannelGroup(channelGroup);

		} catch (Throwable e) {
			LOGGER
					.log(
							Level.SEVERE,
							"Erreur lors de la création d'un nouvelle instance de thème",
							e);
			throw new ServiceRpcException(e);
		} finally {
			LOGGER.info("Fin de la création d'un nouvelle instance de thème");
		}

		return channelGroup;
	}

	/**
	 * Moteur de récupération des données de flux RSS.
	 */
	private FeedEntryDao getFeedEntryDao() {
		if (mockedFeedEntryDao != null) {
			return mockedFeedEntryDao;
		}
		return DaoFactory.getFeedEntryDao();
	}

	/**
	 * Gestionnaire des données de flux et de thèmes.
	 */
	private FeedChannelDao getFeedChannelDao() {
		if (mockedFeedChannelDao != null) {
			return mockedFeedChannelDao;
		}
		return DaoFactory.getFeedChannelDao();
	}

	@Override
	public void removeChannel(FeedChannel channel) throws ServiceRpcException {

		LOGGER.info("Suppression du flux " + channel);

		try {

			FeedChannelDao feedChannelDao = getFeedChannelDao();
			feedChannelDao.deleteFeedChannel(channel);

		} catch (Throwable e) {
			LOGGER.log(Level.SEVERE, "Erreur lors de la suppression du flux "
					+ channel, e);
			throw new ServiceRpcException(e);
		} finally {
			LOGGER.info("Fin de la suppression du flux " + channel);
		}
	}

	@Override
	public void removeChannelGroup(FeedChannelGroup channelGroup)
			throws ServiceRpcException {

		LOGGER.info("Suppression du thème " + channelGroup);

		try {

			FeedChannelDao feedChannelDao = getFeedChannelDao();
			feedChannelDao.deleteFeedChannelGroup(channelGroup);

		} catch (Throwable e) {
			LOGGER.log(Level.SEVERE, "Erreur lors de la suppression du thème "
					+ channelGroup, e);
			throw new ServiceRpcException(e);
		} finally {
			LOGGER.info("Fin de la suppression du thème " + channelGroup);
		}
	}

	/* ********************************************************************** */
	/* ********************************************************************** */
	/* ********************************************************************** */

	private FeedEntryDao mockedFeedEntryDao;
	private FeedChannelDao mockedFeedChannelDao;

	/**
	 * JUnit - Définit un mock pour {@link FeedEntryDao}.
	 */
	void setMockedFeedEntryDao(FeedEntryDao mockedFeedEntryDao) {
		this.mockedFeedEntryDao = mockedFeedEntryDao;
	}

	/**
	 * JUnit - Définit un mock pour {@link FeedChannelDao}.
	 */
	void setMockedFeedChannelDAO(FeedChannelDao mockedFeedChannelDao) {
		this.mockedFeedChannelDao = mockedFeedChannelDao;
	}
}
